﻿using System;
using System.Collections.Generic;
using Firefly.Framework.Collections.Spatial;
using Firefly.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Firefly.Framework.Components.Terrain
{
    public class QuadTerrainNode : QuadTreeNode, IQuadTreeNode
    {
        private int _vertexBufferXOffset;
        private int _vertexBufferYOffset;
        private float _minHeight = 10000;
        private float _maxHeight = 0;
        private float _flatScale;

        public int StitchedSides { get; set; }
        public int NumberOfIndices { get; private set; }
        public int[][] Indices { get; private set; }
        public int VertexBuffer { get; private set; }
        public int StepSize { get; private set; }
        public override Vector3 Offset
        {
            get { return base.Offset; }
            set
            {
                base.Offset = value;
                BoundingBox = new BoundingBox(
                new Vector3((float)(XPosition + Offset.X) * _flatScale, _minHeight + Offset.Y, (float)(YPosition + Offset.Z) * _flatScale),
                new Vector3((float)(XPosition + Offset.X + NodeScale) * _flatScale, _maxHeight + Offset.Y, (float)(YPosition + Offset.Z + NodeScale) * _flatScale));
            }
        }

        public QuadTerrainNode(HeightMap heightMap, NormalMap normalMap, int patchSize, int vertexBufferSize, float flatScale, int nodeDepth, int xPosition, int yPosition, QuadTerrainNode parent, VertexPosition[][] vertices)
        {
            _flatScale = flatScale;
            StitchedSides = 0;
            XPosition = xPosition;
            YPosition = yPosition;
            Parent = parent;
            Status = 0;
            int numberOfVertexBuffers = (int)Math.Pow((heightMap.Height - 1) / (vertexBufferSize - 1), 2);
            int sqrtNumberOfVertexBuffers = (int)Math.Sqrt(numberOfVertexBuffers);
            NodeLevel = (int)Math.Pow(2, (nodeDepth));
            NodeScale = ((heightMap.Height - 1) / NodeLevel) + 1;
            StepSize = (NodeScale - 1) / (patchSize - 1);
            Indices = new int[9][];
            VertexBuffer = (int)(Math.Floor(((float)(XPosition + 1) / heightMap.Width) * sqrtNumberOfVertexBuffers) + (Math.Floor(((float)(yPosition + 1) / heightMap.Height) * sqrtNumberOfVertexBuffers) * sqrtNumberOfVertexBuffers)) + 1;
            int vertexBufferRootScale = 1;

            if (NodeScale > vertexBufferSize)
            {
                VertexBuffer = 0;
                vertexBufferRootScale = (heightMap.Width - 1) / (vertexBufferSize - 1);
                _vertexBufferXOffset = 0;
                _vertexBufferYOffset = 0;
            }
            else
            {
                _vertexBufferXOffset = ((VertexBuffer - 1) % (int)sqrtNumberOfVertexBuffers) * (vertexBufferSize - 1);
                _vertexBufferYOffset = ((VertexBuffer - 1) / (int)sqrtNumberOfVertexBuffers) * (vertexBufferSize - 1);
            }

            GenerateIndexArray(vertices, vertexBufferSize, normalMap, vertexBufferRootScale, heightMap.Width, heightMap.Height);
            BoundingBox = new BoundingBox(new Vector3((float)(XPosition + Offset.X) * flatScale, _minHeight, (float)(YPosition + Offset.Y) * flatScale),
                new Vector3((float)(XPosition + Offset.X + NodeScale) * flatScale, _maxHeight, (float)(YPosition + Offset.Y + NodeScale) * flatScale));
            NodeDepth = nodeDepth;
        }

        private void GenerateIndexArray(VertexPosition[][] vertices, int vertexBufferSize, NormalMap normalMap, int vertexBufferRootScale, int width, int height)
        {
            int stitchingTypeCount = 9;

            for (int stitchingSide = 0; stitchingSide < stitchingTypeCount; stitchingSide++)
            {
                List<int> tempIndices = new List<int>();
                bool addingFlats = false;
                int xOffset = 0;
                Vector3 oldNormal = new Vector3();

                // Build the index arrays for each stitching type.
                for (int y = YPosition; y < YPosition + ((NodeScale - 1) - StepSize + 1); y += StepSize)
                {
                    for (int x = XPosition; x < XPosition + ((NodeScale - 1) - StepSize + 1); x += StepSize)
                    {
                        if (y < width - StepSize && x < height - StepSize)
                        {
                            bool standard = false;

                            if (vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position.Y > _maxHeight)
                            {
                                _maxHeight = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position.Y;
                            }
                            else
                            {
                                if (vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position.Y < _minHeight)
                                {
                                    _minHeight = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position.Y;
                                }
                            }

                            #region Stitch the bottom

                            if (x <= XPosition)
                            {
                                if (stitchingSide == 4 || stitchingSide == 7 || stitchingSide == 8)
                                {
                                    if (y % (StepSize * 2) == 0)
                                    {
                                        standard = false;

                                        // One large stitch.
                                        tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize * 2) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);

                                        NumberOfIndices += 3;

                                        // Two xmall stiches (don't do the edges).
                                        if (y != YPosition || stitchingSide == 8 || stitchingSide == 4)
                                        {
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                        }

                                        if (y != YPosition + (NodeScale - 1) - StepSize * 2 || stitchingSide == 7 || stitchingSide == 4)
                                        {
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize * 2) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize * 2) * vertexBufferSize) / vertexBufferRootScale);
                                        }
                                    }
                                }
                                else
                                {
                                    standard = true;
                                }
                            }

                            #endregion

                            #region Stitch the top

                            if (x == XPosition + ((NodeScale - 1) - StepSize))
                            {
                                if (stitchingSide == 2 || stitchingSide == 5 || stitchingSide == 6)
                                {
                                    if (y % (StepSize * 2) == 0)
                                    {
                                        standard = false;

                                        // One large stitch.
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize * 2) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);

                                        // Two xmall stiches (don't do the edges).
                                        if (y != YPosition || stitchingSide == 2 || stitchingSide == 5)
                                        {
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                        }

                                        if (y != YPosition + (NodeScale - 1) - StepSize * 2 || stitchingSide == 2 || stitchingSide == 6)
                                        {

                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize * 2) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize * 2) * vertexBufferSize) / vertexBufferRootScale);
                                        }
                                    }
                                }
                                else
                                {
                                    standard = true;
                                }
                            }

                            #endregion

                            #region Stitch the right

                            if (y <= YPosition)
                            {
                                if (stitchingSide == 3 || stitchingSide == 6 || stitchingSide == 7)
                                {
                                    if (x % (StepSize * 2) == 0)
                                    {
                                        standard = false;

                                        // One large stitch.
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize * 2) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);

                                        // Two xmall stiches (don't do the edges).
                                        if (x != XPosition || stitchingSide == 3 || stitchingSide == 6)
                                        {
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                        }

                                        if (x != XPosition + (NodeScale - 1) - StepSize * 2 || stitchingSide == 3 || stitchingSide == 7)
                                        {
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize * 2) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize * 2) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        }
                                    }
                                }
                                else
                                {
                                    standard = true;
                                }
                            }

                            #endregion

                            #region Stitch the left

                            if (y == YPosition + ((NodeScale - 1) - StepSize))
                            {
                                if (stitchingSide == 1 || stitchingSide == 5 || stitchingSide == 8)
                                {
                                    if (x % (StepSize * 2) == 0)
                                    {
                                        standard = false;

                                        // One large stitch.
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize * 2) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);

                                        // Two xmall stiches (don't do the edges).
                                        if (x != XPosition || stitchingSide == 1 || stitchingSide == 5)
                                        {
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        }

                                        if (x != XPosition + (NodeScale - 1) - StepSize * 2 || stitchingSide == 1 || stitchingSide == 8)
                                        {

                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize * 2) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize * 2) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale);
                                        }
                                    }
                                }
                                else
                                {
                                    standard = true;
                                }
                            }

                            #endregion

                            if (x > XPosition && y > YPosition && x != XPosition + ((NodeScale - 1) - StepSize) && y != YPosition + ((NodeScale - 1) - StepSize))
                            {
                                standard = true;
                            }

                            #region No stitching (center peice)

                            if (standard == true)
                            {
                                // Reduce the number of polygons by removing detail on flat planes
                                Vector3 next1Normal = normalMap[x, y];
                                Vector3 next2Normal = normalMap[x, y + StepSize];
                                Vector3 next1Position = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position;
                                Vector3 next2Position = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + (y + StepSize - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position;
                                Vector3 nn = vertices[VertexBuffer][Math.Abs((x + StepSize - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position - next1Position;
                                nn.Normalize();
                                Vector3 nn2 = vertices[VertexBuffer][Math.Abs((x + StepSize - _vertexBufferXOffset) + (y + StepSize - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale].Position - next2Position;
                                nn2.Normalize();
                                Vector3 next1Normalised = Vector3.Cross(next1Normal, Vector3.UnitZ);
                                next1Normalised.Normalize();
                                Vector3 next2Normalised = Vector3.Cross(next2Normal, Vector3.UnitZ);
                                next2Normalised.Normalize();
                                
                                if (oldNormal == next1Normal && oldNormal == next2Normal && nn == next1Normalised && nn2 == next2Normalised && x < XPosition + ((NodeScale - 1) - StepSize * 2) || oldNormal == next1Normal && oldNormal == next2Normal && float.IsNaN((next1Normalised.Z)) && nn.X == 1 && nn2.X == 1 && x < XPosition + ((NodeScale - 1) - StepSize * 2))
                                {
                                    if (addingFlats == false)
                                    {
                                        // Entering a flatstrip.
                                        addingFlats = true;
                                        xOffset = x;
                                        oldNormal = normalMap[x, y + StepSize];
                                    }
                                    else
                                    {
                                        // In the middle of a flatstip, do nothing.
                                    }
                                }
                                else
                                {
                                    if (addingFlats == true)
                                    {
                                        // Leave a flatstrip.
                                        addingFlats = false;
                                        tempIndices.Add(Math.Abs(((xOffset - _vertexBufferXOffset)) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs((x - StepSize - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs((x - StepSize - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);

                                        tempIndices.Add(Math.Abs(((xOffset - _vertexBufferXOffset)) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs((x - StepSize - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((xOffset - _vertexBufferXOffset)) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);

                                        // This makes cliffs look better by reorientating the diagonal, and thus removing "cliff feet".
                                        VertexPosition v0 = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale];
                                        VertexPosition vX = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset + StepSize) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale];
                                        VertexPosition vY = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale];
                                        VertexPosition vXY = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale];
                                        float rightDiagDifference = Math.Abs(v0.Position.Y - vXY.Position.Y);
                                        float leftDiagDifference = Math.Abs(vX.Position.Y - vY.Position.Y);
                                        
                                        if (rightDiagDifference < leftDiagDifference)
                                        {
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);                                            
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        }
                                        else
                                        {
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        }

                                        tempIndices.Add(Math.Abs((x - StepSize - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - StepSize - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs((x - StepSize - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs((x - StepSize - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - StepSize - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                        tempIndices.Add(Math.Abs(((x - StepSize - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        oldNormal = normalMap[x, y + StepSize];
                                    }
                                    else
                                    {
                                        // Generate a normal square: nothing special, except for removing cliff feet.
                                        oldNormal = normalMap[x, y + StepSize];

                                        // Make cliffs look better by reorientating the diagonal.
                                        VertexPosition v0 = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale];
                                        VertexPosition vX = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset + StepSize) + ((y - _vertexBufferYOffset)) * vertexBufferSize) / vertexBufferRootScale];
                                        VertexPosition vY = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale];
                                        VertexPosition vXY = vertices[VertexBuffer][Math.Abs((x - _vertexBufferXOffset + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale];
                                        float rightDiagDifference = Math.Abs(v0.Position.Y - vXY.Position.Y);
                                        float leftDiagDifference = Math.Abs(vX.Position.Y - vY.Position.Y);

                                        if (rightDiagDifference < leftDiagDifference)
                                        {
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset)) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        }
                                        else
                                        {
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs((x - _vertexBufferXOffset) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + ((y - _vertexBufferYOffset) + StepSize) * vertexBufferSize) / vertexBufferRootScale);
                                            tempIndices.Add(Math.Abs(((x - _vertexBufferXOffset) + StepSize) + (y - _vertexBufferYOffset) * vertexBufferSize) / vertexBufferRootScale);
                                        }
                                    }
                                }
                            }

                            #endregion
                        }
                    }
                }

                // Keep track of the number of indices.
                Indices[stitchingSide] = new int[tempIndices.Count];

                if (NumberOfIndices < tempIndices.Count)
                {
                    NumberOfIndices = tempIndices.Count;
                }

                Indices[stitchingSide] = tempIndices.ToArray();
            }
        }
    }
}
